// Copyright 2006 Mloofle Inc. All Rights Reserved.

public class Hasher {

  public static int[] computeHashes(String str, int count) {
    long[] result = new long[count];

    for (int i = 0; i < count; ++i) {
      switch (i) {
        case 0:
          result[i] = APHash(str);
          break;
        case 1:
          result[i] = BKDRHash(str);
          break;
        case 2:
          result[i] = BPHash(str);
          break;
        case 3:
          result[i] = DEKHash(str);
          break;
        case 4:
          result[i] = DJBHash(str);
          break;
        case 5:
          result[i] = ELFHash(str);
          break;
        case 6:
          result[i] = FNVHash(str);
          break;
        case 7:
          result[i] = JSHash(str);
          break;
        case 8:
          result[i] = PJWHash(str);
          break;
        case 9:
          result[i] = RSHash(str);
          break;
        case 10:
          result[i] = SDBMHash(str);
          break;
      }
    }

    int[] intres = new int[count];
    for (int i = 0; i < count; ++i) {
      int h = (int) result[i];
      h += ~(h << 9);
      h ^= (h >>> 14);
      h += (h << 4);
      h ^= (h >>> 10);
      intres[i] = h;

    }
    return intres;
  }

  static long RSHash(String str) {
    int b = 378551;
    int a = 63689;
    long hash = 0;

    for (int i = 0; i < str.length(); i++) {
      hash = hash * a + str.charAt(i);
      a = a * b;
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of RS Hash Function */

  static long JSHash(String str) {
    long hash = 1315423911;

    for (int i = 0; i < str.length(); i++) {
      hash ^= ((hash << 5) + str.charAt(i) + (hash >> 2));
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of JS Hash Function */

  static long PJWHash(String str) {
    long BitsInUnsignedInt = 4 * 8;
    long ThreeQuarters = BitsInUnsignedInt * 3 / 4;
    long OneEighth = BitsInUnsignedInt / 8;
    long HighBits = (long) (0xFFFFFFFF) << (BitsInUnsignedInt - OneEighth);
    long hash = 0;
    long test = 0;

    for (int i = 0; i < str.length(); i++) {
      hash = (hash << OneEighth) + str.charAt(i);

      if ((test = hash & HighBits) != 0) {
        hash = ((hash ^ (test >> ThreeQuarters)) & (~HighBits));
      }
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of P. J. Weinberger Hash Function */

  static long ELFHash(String str) {
    long hash = 0;
    long x = 0;

    for (int i = 0; i < str.length(); i++) {
      hash = (hash << 4) + str.charAt(i);

      if ((x = hash & 0xF0000000L) != 0) {
        hash ^= (x >> 24);
        hash &= ~x;
      }
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of ELF Hash Function */

  static long BKDRHash(String str) {
    long seed = 131; // 31 131 1313 13131 131313 etc..
    long hash = 0;

    for (int i = 0; i < str.length(); i++) {
      hash = (hash * seed) + str.charAt(i);
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of BKDR Hash Function */

  static long SDBMHash(String str) {
    long hash = 0;

    for (int i = 0; i < str.length(); i++) {
      hash = str.charAt(i) + (hash << 6) + (hash << 16) - hash;
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of SDBM Hash Function */

  static long DJBHash(String str) {
    long hash = 5381;

    for (int i = 0; i < str.length(); i++) {
      hash = ((hash << 5) + hash) + str.charAt(i);
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of DJB Hash Function */

  static long DEKHash(String str) {
    long hash = str.length();

    for (int i = 0; i < str.length(); i++) {
      hash = ((hash << 5) ^ (hash >> 27)) ^ str.charAt(i);
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of DEK Hash Function */

  static long BPHash(String str) {
    long hash = 0;

    for (int i = 0; i < str.length(); i++) {
      hash = hash << 7 ^ str.charAt(i);
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of BP Hash Function */

  static long FNVHash(String str) {
    long fnv_prime = 0x811C9DC5;
    long hash = 0;

    for (int i = 0; i < str.length(); i++) {
      hash *= fnv_prime;
      hash ^= str.charAt(i);
    }

    return (hash & 0x7FFFFFFF);
  }

  /* End Of FNV Hash Function */

  static long APHash(String str) {
    long hash = 0;

    for (int i = 0; i < str.length(); i++) {
      if ((i & 1) == 0) {
        hash ^= ((hash << 7) ^ str.charAt(i) ^ (hash >> 3));
      } else {
        hash ^= (~((hash << 11) ^ str.charAt(i) ^ (hash >> 5)));
      }
    }

    return (hash & 0x7FFFFFFF);
  }
  /* End Of AP Hash Function */

}
